package com.flyco.modules.oms.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.flyco.common.api.vo.Result;
import com.flyco.common.exception.FlycoException;
import com.flyco.common.system.vo.DictModel;
import com.flyco.common.system.vo.LoginUser;
import com.flyco.common.util.*;
import com.flyco.modules.home.vo.OrderTotalPayAmountVO;
import com.flyco.modules.oms.entity.*;
import com.flyco.modules.oms.mapper.OmsOrderItemMapper;
import com.flyco.modules.oms.mapper.OmsOrderInvoiceMapper;
import com.flyco.modules.oms.mapper.OmsOrderMapper;
import com.flyco.modules.oms.model.OmsOrderModel;
import com.flyco.modules.oms.service.*;
import com.flyco.modules.oms.vo.OmsOrderPage;
import com.flyco.modules.oms.vo.OmsSendOrderDto;
import com.flyco.modules.oms.vo.OmsSendOrderItem;
import com.flyco.modules.pms.entity.PmsProduct;
import com.flyco.modules.pms.entity.PmsSkuStock;
import com.flyco.modules.pms.service.IPmsProductService;
import com.flyco.modules.pms.service.IPmsSkuStockService;
import com.flyco.modules.returns.entity.OmsOrderReturnApply;
import com.flyco.modules.returns.service.IOmsOrderReturnApplyService;
import com.flyco.modules.returns.service.IOmsSendOutService;
import com.flyco.modules.stm.entity.StmBizInoutRelation;
import com.flyco.modules.stm.entity.StmChannelInfo;
import com.flyco.modules.stm.entity.StmDealerDiscount;
import com.flyco.modules.stm.entity.StmStoreInfo;
import com.flyco.modules.stm.service.*;
import com.flyco.modules.system.entity.SysMail;
import com.flyco.modules.system.entity.SysPermission;
import com.flyco.modules.system.entity.SysRolePermission;
import com.flyco.modules.system.entity.SysUser;
import com.flyco.modules.system.service.*;
import com.flyco.modules.ums.model.UmsMemberReceiveAddressModel;
import com.flyco.modules.ums.service.IUmsMemberReceiveAddress;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.tomcat.jni.File;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.Serializable;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 订单管理
 * @Author: flyco
 * @Date: 2019-12-10
 * @Version: V1.0
 */
@Slf4j
@Service
public class OmsOrderServiceImpl extends ServiceImpl<OmsOrderMapper, OmsOrder> implements IOmsOrderService {

    @Autowired
    private OmsOrderMapper omsOrderMapper;
    @Autowired
    private OmsOrderItemMapper omsOrderItemMapper;
    @Autowired
    private OmsOrderInvoiceMapper omsOrderInvoiceMapper;
    @Autowired
    private IOmsOrderTraceService omsOrderTraceService;
    @Autowired
    private IOmsOrderItemService omsOrderItemService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private IPmsProductService pmsProductService;
    @Autowired
    private IStmStoreInfoService stmStoreInfoService;
    @Autowired
    private IStmChannelInfoService channelInfoService;
    @Autowired
    private IOmsOrderReturnApplyService omsOrderReturnApplyService;
    @Autowired
    private IUmsMemberReceiveAddress iUmsMemberReceiveAddress;

    @Autowired
    private IStmBizInoutRelationService stmBizInoutRelationService;
    @Autowired
    private IStmJdSendOrderItemService sendOrderItemService;
    @Autowired
    private IStmJdSendOrderService sendOrderService;
    @Autowired
    private IStmBizInoutRelationService bizInoutRelationService;
    @Autowired
    private ISysDictService dictService;
    @Autowired
    private IOmsOrderSettingService omsOrderSettingService;
    @Autowired
    private IStmDealerDiscountService dealerDiscountService;
    @Autowired
    private IOmsOrderDiscountRecordService discountRecordService;

    @Value(value = "${spring.mailTemp.path}")
    private String path;

    @Override
    public OmsOrder addSendOrder(OmsSendOrderDto sendOrderDto, LoginUser sysUser, Long applyId) {
        OmsOrderPage omsOrderPage = new OmsOrderPage();
        omsOrderPage.setOrderSource(2);
        omsOrderPage.setOrderType(2);
        omsOrderPage.setNote(sendOrderDto.getNote());
        omsOrderPage.setChannelId(sendOrderDto.getChannelId());
        omsOrderPage.setStoreId(sendOrderDto.getStoreId());
        omsOrderPage.setCompanyAddressId(sendOrderDto.getCompanyAddressId());
        omsOrderPage.setOmsOrderItemList(sendOrderDto.getOmsOrderItemList().stream().map(one -> {
            OmsOrderItem orderItem = new OmsOrderItem();
            orderItem.setProductPrice(one.getBoxPrice());
            orderItem.setProductId(one.getProductId());
            orderItem.setMinUnitQuantity(one.getMinUnitQuantity());
            orderItem.setProductQuantity(one.getProductQuantity());
            orderItem.setTotalRealAmount(one.getTotalAmount());
            return orderItem;
        }).collect(Collectors.toList()));

        //创建订单（发货单）
        OmsOrder omsOrder = this.addOmsOrder(omsOrderPage, false, false);

        OmsOrderTrace omsOrderTrace = new OmsOrderTrace();
        omsOrderTrace.setOrderId(applyId.toString());
        omsOrderTrace.setCreateTime(new Date());
        omsOrderTrace.setLabel("补发订单");
        omsOrderTrace.setContent(omsOrder.getId());
        omsOrderTraceService.save(omsOrderTrace);

        //创建出库单
        createStockOut(omsOrder, sysUser);

        //把发货订单id回写到退换货申请表中
        updateReturnApplyInfo(omsOrder, applyId);

        return omsOrder;
    }

    @Override
    public Result payment(String orderId, LoginUser sysUser) {

        OmsOrder omsOrder = this.getById(orderId);

        //更新订单状态为已支付，待发货
        OmsOrder order = new OmsOrder();
        order.setPayStatus(4);
        order.setProductStatus(3);
        order.setEffectiveAmount(omsOrder.getPayAmount());
        order.setPaymentTime(new Date());
        order.setPaymentBy(sysUser.getRealname());
        boolean update = this.update(order, Wrappers.lambdaUpdate(OmsOrder.class).eq(OmsOrder::getId, orderId).eq(OmsOrder::getCancelFlag, 0)
                .eq(OmsOrder::getStatus, 1).eq(OmsOrder::getPayStatus, 1).eq(OmsOrder::getProductStatus, 1));
        if (!update) {
            return Result.error("数据过期，请刷新页面重试");
        }
        /*List<OmsOrderItem> orderItems = omsOrderItemService.selectByMainId(orderId);
        pmsSkuStockService.releaseSkuStockLock(orderItems);*/

        OmsOrder omsOrderNew = this.getById(orderId);
        createStockOut(omsOrderNew, sysUser);

        return Result.ok("成功!");
    }

    //把发货订单id回写到退换货申请表中
    private void updateReturnApplyInfo(OmsOrder omsOrder, Long applyId) {

        OmsOrderReturnApply returnApply = omsOrderReturnApplyService.getById(applyId);
        returnApply.setSendOrderId(omsOrder.getId());
        omsOrderReturnApplyService.updateById(returnApply);
    }

    /**
     * 发货信息初始化
     * 这里初始化发货信息，仓库才能操作出库
     */
    private void createStockOut(OmsOrder omsOrder, LoginUser sysUser) {

        StmBizInoutRelation stmBizInoutRelation = new StmBizInoutRelation();
        stmBizInoutRelation.setPartnerId(omsOrder.getPartnerId());
        //门店信息
        stmBizInoutRelation.setStoreId(0L);
        stmBizInoutRelation.setStoreName("总仓");
        //收货门店信息
        stmBizInoutRelation.setSourceStoreId(omsOrder.getStoreId());
        StmStoreInfo storeInfo = stmStoreInfoService.getByStoreId(omsOrder.getStoreId());
        if (storeInfo != null) {
            stmBizInoutRelation.setSourceStoreName(storeInfo.getName());
        }
        stmBizInoutRelation.setStatus(1);
        stmBizInoutRelation.setType("STOCK_OUT");
        stmBizInoutRelation.setStockBizType("STOCK_OUT_TYPE_SALE");
        stmBizInoutRelation.setSourceType("RECEIPT_TYPE_SALE");
        stmBizInoutRelation.setSourceId(Long.parseLong(omsOrder.getId()));
        stmBizInoutRelation.setOrderId(omsOrder.getId());
        stmBizInoutRelation.setCreateBy(sysUser.getRealname());
        stmBizInoutRelation.setCreateTime(omsOrder.getPaymentTime());
        stmBizInoutRelationService.save(stmBizInoutRelation);
    }

    @Transactional
    @Override
    public OmsOrder addOmsOrder(OmsOrderPage omsOrderPage, Boolean needComputeAmount, Boolean needApprove) {

        OmsOrder omsOrder = new OmsOrder();
//        if (omsOrderPage.getOrderSource().equals(1)) {
        //只有后台补发目前往订单表插入订单数据
        omsOrder = addOrderAndTrace(omsOrderPage, needComputeAmount, needApprove);
//        }

        //往发货单表插入数据（oms_send_out）插入发货单数据
//        sendOutService.addSendOrder(omsOrderPage);

        return omsOrder;
    }


    public OmsOrder addOrderAndTrace(OmsOrderPage omsOrderPage, Boolean needComputeAmount, Boolean needApprove) {

        //往订单主表插入数据
        OmsOrder omsOrder = addOrder(omsOrderPage, needApprove);

        //添加订单详情
        addOrderItem(omsOrderPage, omsOrder, needComputeAmount);

        OmsOrderTrace omsOrderTrace = new OmsOrderTrace();
        omsOrderTrace.setOrderId(omsOrder.getId());
        omsOrderTrace.setCreateTime(new Date());
        omsOrderTrace.setLabel("提交订单");
        omsOrderTrace.setContent("您的订单已提交");
        omsOrderTraceService.save(omsOrderTrace);

        return omsOrder;
    }


    public OmsOrder addOrder(OmsOrderPage omsOrderPage, Boolean needApprove) {
        OmsOrder omsOrder = new OmsOrder();
        BeanUtils.copyProperties(omsOrderPage, omsOrder);
        if (Objects.equals(omsOrderPage.getOrderSource(), 1)) {
            //后台创建
            omsOrder.setId(IdUtil.createOrderId(new Date(), "manager", false));
        } else if (Objects.equals(omsOrderPage.getOrderSource(), 2)) {
            //补发
            omsOrder.setId(IdUtil.createOrderId(new Date(), "returnOrder", false));
        }

        omsOrder.setPartnerId(0l);
        omsOrder.setMemberId(omsOrder.getStoreId());
        omsOrder.setOrderSn(omsOrder.getId());
        omsOrder.setCustomerType(5);
        StmStoreInfo stmStoreInfo = stmStoreInfoService.getByStoreId(omsOrder.getStoreId());
        UmsMemberReceiveAddressModel umsMemberReceiveAddressModel = iUmsMemberReceiveAddress.getById(omsOrder.getCompanyAddressId());
        omsOrder.setCompanyName(stmStoreInfo.getName());
        omsOrder.setCompanyCode(stmStoreInfo.getId());
        omsOrder.setMemberUsername(stmStoreInfo.getLinkName());
        omsOrder.setTotalAmount(BigDecimal.ZERO);
        omsOrder.setPayAmount(BigDecimal.ZERO);
        omsOrder.setEffectiveAmount(BigDecimal.ZERO);
        omsOrder.setPayType("icbcToBPay");
        omsOrder.setSourceType("mini");
        omsOrder.setSourceSystem("online");
        omsOrder.setAddressId(umsMemberReceiveAddressModel.getId());
        omsOrder.setReceiverPhone(stmStoreInfo.getPhone());
        omsOrder.setReceiverName(stmStoreInfo.getLinkName());
        omsOrder.setReceiverProvince(umsMemberReceiveAddressModel.getProvince());
        omsOrder.setReceiverProvinceCode(umsMemberReceiveAddressModel.getProvinceCode());
        omsOrder.setReceiverCity(umsMemberReceiveAddressModel.getCity());
        omsOrder.setReceiverCityCode(umsMemberReceiveAddressModel.getCityCode());
        omsOrder.setReceiverRegion(umsMemberReceiveAddressModel.getRegion());
        omsOrder.setReceiverRegionCode(umsMemberReceiveAddressModel.getAreaCode());
        omsOrder.setTown(umsMemberReceiveAddressModel.getTown());
        omsOrder.setTownCode(umsMemberReceiveAddressModel.getTownCode());
        omsOrder.setDistance(umsMemberReceiveAddressModel.getDistance());
        omsOrder.setReceiverDetailAddress(umsMemberReceiveAddressModel.getDetailAddress());
        if (needApprove) {
            omsOrder.setStatus(0);
            omsOrder.setProductStatus(1);
            omsOrder.setPayStatus(1);
        } else {
            omsOrder.setStatus(1);
            omsOrder.setProductStatus(3);
            omsOrder.setPayStatus(4);
        }
        StmChannelInfo channelInfo = channelInfoService.getById(omsOrder.getChannelId());
        omsOrder.setChannelName(channelInfo.getName());
        omsOrder.setCustomerCode(stmStoreInfo.getCompanyCode().toString());

        //获取销售
        SysUser saleUser = userService.getById(stmStoreInfo.getSaleUserId());
        if (saleUser != null) {
            omsOrder.setSaleUserId(Long.valueOf(saleUser.getId()));
            omsOrder.setSaleUserName(saleUser.getRealname());
            omsOrder.setSaleJdCode(saleUser.getJdCode());
        }
        this.save(omsOrder);
        return omsOrder;
    }

    public void addOrderItem(OmsOrderPage omsOrderPage, OmsOrder omsOrder, Boolean needComputeAmount) {
        BigDecimal zero = new BigDecimal(0);
        BigDecimal totalAmount = zero;
        for (OmsOrderItem entity : omsOrderPage.getOmsOrderItemList()) {
            PmsProduct pmsProduct = pmsProductService.getById(entity.getProductId());
            entity.setId(IdGenerator16Bit.getInstance().nextId());
            entity.setProductId(pmsProduct.getId());
            entity.setProductBrand(pmsProduct.getBrandName());
            entity.setProductName(pmsProduct.getName());
            entity.setProductSkuCode(pmsProduct.getSkuCode());
            entity.setProductSkuUnit(pmsProduct.getSkuUnit());
            entity.setProductUnit(pmsProduct.getUnit());
            entity.setOrderId(omsOrder.getId());
            entity.setOrderSn(omsOrder.getId());
            entity.setProductSkuSpec(Integer.valueOf(pmsProduct.getSkuSpec()));
            entity.setProductPic(pmsProduct.getPic());
            if (omsOrderPage.getOrderSource().equals(1)) {
                //后台创建的，需要再算一个minUnitQuantity。补发的再创建的时候已经算好了。
                entity.setMinUnitQuantity(entity.getProductQuantity() * entity.getProductSkuSpec());
            }
            entity.setSp1(pmsProduct.getBrandCategory().toString());
            if (needComputeAmount) {
                entity.setProductPrice(entity.getProductPrice());
                entity.setRealAmount(entity.getProductPrice());
                entity.setTotalRealAmount(entity.getProductPrice().multiply(new BigDecimal(entity.getProductQuantity())));
                totalAmount = totalAmount.add(entity.getTotalRealAmount());
            } else {
                entity.setProductPrice(BigDecimal.ZERO);
                entity.setRealAmount(BigDecimal.ZERO);
                entity.setTotalRealAmount(BigDecimal.ZERO);
            }
        }
        omsOrderItemService.saveBatch(omsOrderPage.getOmsOrderItemList());

        //更新订单金额
        if (needComputeAmount) {
            omsOrder.setTotalAmount(totalAmount);
            omsOrder.setPayAmount(totalAmount);
            updateById(omsOrder);
        }
    }

    /**
     * 生成18位订单编号:8位日期+2位平台号码+2位支付方式+6位以上自增id
     */
    @Override
    public String generateOrderSn() {
        String date = new SimpleDateFormat("yyyyMMddHH").format(new Date());
        String key = "portal:orderId:" + date;
        long seq = redisUtil.incr(key, 1);
        if (seq == 1L) {
            seq = redisUtil.incr(key, (long) (Math.random() * 500000));
            redisUtil.expire(key, 3600 * 2L);
        }
        return "" + IdUtil.genId("yyMMddHH{s}{s}{s}{s}{s}{r}{s}2", seq, 6);
    }

    @Override
    @Transactional
    public void saveMain(OmsOrder omsOrder, List<OmsOrderItem> omsOrderItemList, List<OmsOrderInvoice> omsOrderInvoiceList) {
        omsOrderMapper.insert(omsOrder);
        for (OmsOrderItem entity : omsOrderItemList) {
            //外键设置
            entity.setOrderId(omsOrder.getId());
            entity.setOrderSn(omsOrder.getId());
            omsOrderItemMapper.insert(entity);
        }
        if (oConvertUtils.isNotEmpty(omsOrderInvoiceList)) {
            for (OmsOrderInvoice entity : omsOrderInvoiceList) {
                //外键设置
                entity.setOrderId(omsOrder.getId());
                omsOrderInvoiceMapper.insert(entity);
            }
        }
    }

    @Override
    @Transactional
    public void updateMain(OmsOrder omsOrder, List<OmsOrderItem> omsOrderItemList, List<OmsOrderInvoice> omsOrderInvoiceList) {
        omsOrderMapper.updateById(omsOrder);

        //1.先删除子表数据
        omsOrderItemMapper.deleteByMainId(omsOrder.getId());
        omsOrderInvoiceMapper.deleteByMainId(omsOrder.getId());

        //2.子表数据重新插入
        for (OmsOrderItem entity : omsOrderItemList) {
            //外键设置
            entity.setOrderId(omsOrder.getId());
            omsOrderItemMapper.insert(entity);
        }
        if (oConvertUtils.isNotEmpty(omsOrderInvoiceList)) {
            for (OmsOrderInvoice entity : omsOrderInvoiceList) {
                //外键设置
                entity.setOrderId(omsOrder.getId());
                omsOrderInvoiceMapper.insert(entity);
            }
        }
    }

    @Override
    @Transactional
    public void delMain(String id) {
        omsOrderItemMapper.deleteByMainId(id);
        omsOrderInvoiceMapper.deleteByMainId(id);
        omsOrderMapper.deleteById(id);
    }

    @Override
    @Transactional
    public void delBatchMain(Collection<? extends Serializable> idList) {
        for (Serializable id : idList) {
            omsOrderItemMapper.deleteByMainId(id.toString());
            omsOrderInvoiceMapper.deleteByMainId(id.toString());
            omsOrderMapper.deleteById(id);
        }
    }

    @Override
    public Map<String, Object> indexOrderInit() {
        return omsOrderMapper.indexOrderInit();
    }

    @Override
    public List<Map<String, Object>> indexOrderBar() {
        return omsOrderMapper.indexOrderBar();
    }

    @Override
    public List<Map<String, Object>> indexOrderMiniArea() {
        return omsOrderMapper.indexOrderMiniArea();
    }

    @Override
    public List<Map<String, Object>> indexOrderRank() {
        return omsOrderMapper.indexOrderRank();
    }

    @Override
    public List<OrderTotalPayAmountVO> indexOrderTotalPayAmount(Date dayStart, Date dayEnd) {
        return omsOrderMapper.indexOrderTotalPayAmount(dayStart, dayEnd);
    }

    @Override
    @Transactional
    public void confirmBatch(Collection<? extends Serializable> idList) {
        OmsOrder changeOrder = new OmsOrder();
        changeOrder.setStatus(1);
        changeOrder.setProductStatus(2);
        LambdaQueryWrapper<OmsOrder> query = new LambdaQueryWrapper<>();
        query.in(OmsOrder::getId, idList);
        query.eq(OmsOrder::getStatus, 0);
        query.eq(OmsOrder::getProductStatus, 1);
        query.in(OmsOrder::getPayStatus, Arrays.asList(0, 4));
        List<OmsOrderTrace> traces = new ArrayList<>();
        for (Object id : idList) {
            OmsOrderTrace trace = new OmsOrderTrace();
            trace.setOrderId(id.toString());
            trace.setLabel("已确认");
            trace.setContent("您的订单已确认");
            trace.setCreateTime(new Date());
            traces.add(trace);
        }
        this.update(changeOrder, query);
        omsOrderTraceService.saveBatch(traces);
    }

    @Override
    @Transactional
    public void innerConfirmBatch(Collection<? extends Serializable> idList) {
        OmsOrder changeOrder = new OmsOrder();
        //changeOrder.setStatus(1);
        changeOrder.setProductStatus(2);
        LambdaQueryWrapper<OmsOrder> query = new LambdaQueryWrapper<>();
        query.in(OmsOrder::getId, idList);
        query.eq(OmsOrder::getOrderType, 3);    //仅处理内购订单
        query.eq(OmsOrder::getStatus, 1);
        query.eq(OmsOrder::getProductStatus, 1);
        query.in(OmsOrder::getPayStatus, Arrays.asList(4));
        List<OmsOrder> orderList = this.list(query);
        List<OmsOrderTrace> traces = new ArrayList<>();
        for (OmsOrder order : orderList) {
            OmsOrderTrace trace = new OmsOrderTrace();
            trace.setOrderId(order.getId());
            trace.setLabel("已审核");
            trace.setContent("您的订单已审核");
            trace.setCreateTime(new Date());
            traces.add(trace);
        }
        this.update(changeOrder, query);
        if (traces.size() > 0) {
            omsOrderTraceService.saveBatch(traces);
        }
    }

    @Override
    @Transactional
    public void groupBuyConfirmBatch(Collection<? extends Serializable> idList) {
        OmsOrder changeOrder = new OmsOrder();
        //changeOrder.setStatus(1);
        changeOrder.setProductStatus(2);
        LambdaQueryWrapper<OmsOrder> query = new LambdaQueryWrapper<>();
        query.in(OmsOrder::getId, idList);
        query.eq(OmsOrder::getOrderType, 4);    //仅处理团购订单
        query.eq(OmsOrder::getStatus, 1);
        query.eq(OmsOrder::getProductStatus, 1);
        query.in(OmsOrder::getPayStatus, Arrays.asList(4));
        List<OmsOrder> orderList = this.list(query);
        List<OmsOrderTrace> traces = new ArrayList<>();
        for (OmsOrder order : orderList) {
            OmsOrderTrace trace = new OmsOrderTrace();
            trace.setOrderId(order.getId());
            trace.setLabel("已审核");
            trace.setContent("您的订单已审核");
            trace.setCreateTime(new Date());
            traces.add(trace);
        }
        this.update(changeOrder, query);
        if (traces.size() > 0)
            omsOrderTraceService.saveBatch(traces);
    }

    @Override
    public Page<OmsOrder> getLiveOrderPage(Page<OmsOrder> page, Wrapper<OmsOrder> wrapper) {
        return page.setRecords(omsOrderMapper.getLiveOrderPage(page, wrapper));
    }

    @Override
    public Page<OmsOrder> getInnerOrderPage(Page<OmsOrder> page, Wrapper<OmsOrder> wrapper) {
        return page.setRecords(omsOrderMapper.getInnerOrderPage(page, wrapper));
    }

    @Override
    public Page<OmsOrder> getGroupBuyOrderPage(Page<OmsOrder> page, Wrapper<OmsOrder> wrapper) {
        return page.setRecords(omsOrderMapper.getGroupBuyOrderPage(page, wrapper));
    }

    @Override
    public void sendMailAfterApprove(String orderId) {

//        OmsOrder orderInfo = getById(orderId);
//        StmStoreInfo storeInfo = stmStoreInfoService.getByStoreId(orderInfo.getStoreId());
//        if (storeInfo == null) {
//            return;
//        }
//        StmChannelInfo channelInfo = channelInfoService.getById(orderInfo.getChannelId());
//        if (channelInfo == null) {
//            return;
//        }
//        String content = orderId + "-" + storeInfo.getName() + "-" + channelInfo.getName();
//        List<SysUser> userList = new ArrayList<>();
//        String subject = "";
//        String realPath = "";
//        switch (orderInfo.getStatus()) {
//            case 10:
//                //根据物料审核按钮的code获取到有权限访问该按钮的用户列表
//                userList = permissionService.getUserListByPerms("order:logisticsAprove");
//                realPath = path + "/approveMailContent.html";
//                subject = "江心味业订货平台新订单审核通知";
//                break;
//            case 9:
//                // 物流审核通过后，状态变成10，财务审核
//                userList = permissionService.getUserListByPerms("order:finaceAprove");
//                realPath = path + "/approveMailContent.html";
//                subject = "江心味业订货平台新订单审核通知";
//                break;
//            case 1:
//                // 财务员审核，订单变成1 ，待出库，发提醒给仓库管理员
//                userList = userService.getByPositionId(1);
//                realPath = path + "/warehouseMailContent.html";
//                subject = "江心味业订货平台新订单出库通知";
//                break;
//        }
//
//        if (CollectionUtils.isEmpty(userList)) {
//            return;
//        }
//        String mails = userList.stream().filter(o -> !StringUtils.isEmpty(o.getEmail())).map(o -> o.getEmail()).collect(Collectors.joining(";"));
//        if (StringUtils.isEmpty(mails)) {
//            return;
//        }
//
//        SysMail mail = new SysMail();
//        String tempContent = FileUtil.readFile(realPath);
//        tempContent = tempContent.replaceAll("%s", content);
//        mail.setContent(tempContent);
//        mail.setReceive(mails);
//        mail.setBusinessType("orderApprove");
//        mail.setSubject(subject);
//        mail.setSourceId(orderId);
//        mailService.sendMail(mail);
    }

    @Override
    public void sendMsgAfterApprove(String orderId) {
        //跟单员审核后发送短信通知 by martin 2024-04-03
        try {
            //审核通过后， 10 物流，9 财务 才发送短信提醒
            DictModel dictModel = dictService.queryDictItemsByCode("msgAddress").get(0);
            String msgUrl = dictModel.getValue() + "/api/back/0-0/sendSms/orderConfirm/" + orderId;
            RestUtil.get(msgUrl);
        } catch (Exception ex) {
            log.error("sendMsgAfterApprove 异常;msg=" + ex.getMessage());
        }
    }

    @Override
    public Boolean clearWxJxCache() {

        DictModel dictModel = dictService.queryDictItemsByCode("clearWxJxCacheUrl").get(0);
        String cacheUrl = dictModel.getValue();
        RestUtil.get(cacheUrl);
        return true;
    }


    /**
     * 批量设置订单是否批量发货
     */
    @Override
    public void batchSetOrderDivideSendFlag() {

        //1 获取所有的待发货订单（status=1，divideSendFlag=0）或部分发货单（status=2，divideSendFlag=1）
        LambdaQueryWrapper<OmsOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(OmsOrder::getStatus, 1, 2).in(OmsOrder::getDivideSendFlag, 0, 1);
        List<OmsOrder> orderList = omsOrderMapper.selectList(wrapper);

        //2 每个待发货订单去查找发货单，如果单个发货单的明细数量跟发货单明细的数量不一样，说明是多次发货
        orderList.forEach(order -> {

            List<StmJdSendOrder> sendOrderList = sendOrderService.getCompleteByOrderId(order.getId());
            if (!CollectionUtils.isEmpty(sendOrderList)) {
                List<String> stockOutIdList = sendOrderList.stream().map(o -> o.getStockoutId()).collect(Collectors.toList());
                List<StmJdSendOrderItem> sendOrderItems = sendOrderItemService.getByJdSendOrderId(stockOutIdList);
                Map<String, List<StmJdSendOrderItem>> mapSendOrderList = sendOrderItems
                        .stream()
                        .collect(Collectors.groupingBy(StmJdSendOrderItem::getStockoutId));
                //发货单的总发货数量
                Integer sendOrderProductCount = sendOrderItems.stream().mapToInt(StmJdSendOrderItem::getProductCount).sum();

                List<OmsOrderItem> orderItemList = omsOrderItemService.selectByMainId(order.getId());
                //订单中的总购买数量
                Integer orderProductCount = orderItemList.stream().mapToInt(OmsOrderItem::getMinUnitQuantity).sum();

                if (mapSendOrderList.size() > 1) {
                    order.setDivideSendFlag(1);
//                    order.setDeliveryTime(new Date(Long.valueOf(sendOrderList.get(0).getCreated())));
                    order.setDeliveryTime(new Date());
                    order.setDeliveryCompany(sendOrderList.get(0).getLogisticsName());
                    order.setDeliverySn(sendOrderList.get(0).getLogisticsNo());
                    if (order.getStatus().equals(1)) {
                        order.setStatus(2);
                        if (order.getProductStatus().equals(3)) {
                            order.setProductStatus(4);
                        }
                        order.setPayStatus(4);
                    }
                } else if (mapSendOrderList.size() == 1) {
                    //如果无法通过多个发货单来确定，就把唯一的发货单的数量跟订单明细数量进行比较。如果比订单明细小，也说明是分批发货
                    if (orderProductCount > sendOrderProductCount) {
                        order.setDivideSendFlag(1);
                    } else {
                        order.setDivideSendFlag(2);
                    }
                    if (order.getStatus().equals(1)) {
                        order.setStatus(2);
                        if (order.getProductStatus().equals(3)) {
                            order.setProductStatus(4);
                        }
                        order.setPayStatus(4);
                    }
                    order.setDeliveryTime(new Date(Long.valueOf(sendOrderList.get(0).getCreated())));
                    order.setDeliveryCompany(sendOrderList.get(0).getLogisticsName());
                    order.setDeliverySn(sendOrderList.get(0).getLogisticsNo());
                }
                //设置是否发货完成
                if (sendOrderProductCount >= orderProductCount) {
                    order.setSendType(1);
                } else {
                    order.setSendType(0);
                }
                order.setUpdateTime(new Date());
                updateById(order);
                bizInoutRelationService.InsertBySendOrderList(order, sendOrderList);
                saveOrderTrace(order, sendOrderList);
            }

        });
    }

    private Result saveOrderTrace(OmsOrder orderInfo, List<StmJdSendOrder> sendOrderList) {

        //因为一个订单可能会重复拉取发货单，所以在写日志时，需要看发货单日志是否已写
        OmsOrderTrace omsOrderTrace;
        for (StmJdSendOrder stmJdSendOrder : sendOrderList) {
            omsOrderTrace = omsOrderTraceService.getBySendOrderId(stmJdSendOrder.getStockoutId());
            if (omsOrderTrace != null) {
                continue;
            }
            omsOrderTrace = new OmsOrderTrace();
            omsOrderTrace.setOrderId(orderInfo.getId());
            omsOrderTrace.setCreateTime(new Date());
            if (orderInfo.getDivideSendFlag().equals(2)) {
                omsOrderTrace.setLabel("发货确认");
                omsOrderTrace.setContent("发货单：" + orderInfo.getId());
                omsOrderTrace.setLogisticsName(stmJdSendOrder.getLogisticsName());
                omsOrderTrace.setTraceNo(stmJdSendOrder.getLogisticsNo());
            } else if (orderInfo.getDivideSendFlag().equals(1)) {
                omsOrderTrace.setLabel("部分发货");
                omsOrderTrace.setLogisticsName(stmJdSendOrder.getLogisticsName());
                omsOrderTrace.setTraceNo(stmJdSendOrder.getLogisticsNo());
                omsOrderTrace.setContent("发货单：" + orderInfo.getId());
            }
            omsOrderTrace.setSendOrderId(stmJdSendOrder.getStockoutId());
            omsOrderTraceService.save(omsOrderTrace);
        }
        return Result.ok("成功!");
    }


    /**
     * 处理旺店通已取消的发货单
     */
    @Override
    public void handleCancelJdSendOrder() {

        List<StmJdSendOrder> sendOrderList = sendOrderService.getCancelJdSendOrderList(5);
        //1 判断是否取消了出库单
        bizInoutRelationService.cancelByJdSendOrderList(sendOrderList);

        log.info("handleCancelJdSendOrder sendOrderList" + JSONUtil.toJsonStr(sendOrderList));

        List<OmsOrder> orderList = new ArrayList<>();
        //2 判断订单表是否要更新状态
        for (StmJdSendOrder jdSendOrder : sendOrderList) {

            //查询订单下是否还有有效的发货单，
            List<StmJdSendOrder> completeSendOrderList = sendOrderService.getCompleteByOrderId(jdSendOrder.getSrcTradeNo());
            OmsOrder orderInfo = omsOrderMapper.selectById(jdSendOrder.getSrcTradeNo());
            if (orderInfo.getStatus().equals(2)) {
                if (CollectionUtils.isEmpty(completeSendOrderList)) {
                    //该订单下已无完成发货单，则把订单的状态改成未发货
                    orderInfo.setStatus(1);
                    orderInfo.setDivideSendFlag(0);
                    orderInfo.setUpdateTime(new Date());
                    updateById(orderInfo);
                    log.info("handleCancelJdSendOrder 把订单状态改成未发货：" + JSON.toJSONString(orderInfo));
//                    orderList.add(orderInfo);
                } else {
                    //存在已完成的发货单，需要判断发货单明细
                    List<String> stockOutIdList = sendOrderList.stream().map(o -> o.getStockoutId()).collect(Collectors.toList());
                    List<StmJdSendOrderItem> sendOrderItems = sendOrderItemService.getByJdSendOrderId(stockOutIdList);

                    List<OmsOrderItem> orderItemList = omsOrderItemService.selectByMainId(orderInfo.getId());
                    Integer orderProductCount = orderItemList.stream().mapToInt(OmsOrderItem::getMinUnitQuantity).sum();
                    Integer sendOrderProductCount = sendOrderItems.stream().mapToInt(StmJdSendOrderItem::getProductCount).sum();
                    if (orderProductCount > sendOrderProductCount) {
                        orderInfo.setDivideSendFlag(1);
                    } else {
                        orderInfo.setDivideSendFlag(0);
                    }
                    orderInfo.setUpdateTime(new Date());
                    updateById(orderInfo);
                    log.info("handleCancelJdSendOrder 修改发货单状态：" + JSON.toJSONString(orderInfo));
//                    orderList.add(orderInfo);
                }
            }

        }
//        if (!CollectionUtils.isEmpty(orderList)) {
//            updateBatchById(orderList);
//        }
    }

    /**
     * 查询门店一段时间内的订单Id
     */
    @Override
    public List<OmsOrder> getOrderList(Long storeId, LocalDateTime beginTime) {
        LambdaQueryWrapper<OmsOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OmsOrder::getStoreId, storeId)
                .in(OmsOrder::getStatus, Arrays.asList(2, 3, 5))
                .ge(OmsOrder::getCreateTime, beginTime);

        return list(wrapper);
    }

    @Override
    public List<OmsOrder> getOrderList(Long storeId) {

        LambdaQueryWrapper<OmsOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OmsOrder::getStoreId, storeId)
                .in(OmsOrder::getStatus, Arrays.asList(1, 2, 3, 5));

        return list(wrapper);
    }

    /**
     * 定时给物流提货状态的订单发送短息通知
     */
    @Override
    public void sendPickupMsg() {
        //根据配置确认是否要发送短信通知
        OmsOrderSetting orderSetting = omsOrderSettingService.getOne();
        if (orderSetting != null && (orderSetting.getEnableSms().equals(1) || orderSetting.getEnableWx().equals(1))) {
            LambdaQueryWrapper<OmsOrder> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(OmsOrder::getStatus, 13)
                    .eq(OmsOrder::getSmsStatus, 1)
                    .isNotNull(OmsOrder::getLogisticsPickupTime)
                    .isNotNull(OmsOrder::getDeliverySn)
                    .isNotNull(OmsOrder::getDeliveryCompany);
            List<OmsOrder> orderList = omsOrderMapper.selectList(wrapper);
            if (!orderList.isEmpty()) {
                //发送短信提醒
                DictModel dictModel = dictService.queryDictItemsByCode("msgAddress").get(0);
                for (OmsOrder order : orderList) {
                    String msgUrl = dictModel.getValue() + "/api/back/0-0/sendSms/orderStockOut/" + order.getId();
                    RestUtil.get(msgUrl);
                }
            }
        }
    }

    @Override
    public void sendOrderAuditMsg() {
        //根据配置确认是否要发送短信通知
        OmsOrderSetting orderSetting = omsOrderSettingService.getOne();
        if (orderSetting != null && (orderSetting.getEnableSms().equals(1) || orderSetting.getEnableWx().equals(1))) {
            LambdaQueryWrapper<OmsOrder> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(OmsOrder::getStatus, 5).eq(OmsOrder::getSmsStatus, 0);
            List<OmsOrder> orderList = omsOrderMapper.selectList(wrapper);
            if (!orderList.isEmpty()) {
                //审核通过后， 10 物流，9 财务 才发送短信提醒
                DictModel dictModel = dictService.queryDictItemsByCode("msgAddress").get(0);
                for (OmsOrder order : orderList) {
                    String msgUrl = dictModel.getValue() + "/api/back/0-0/sendSms/orderConfirm/" + order.getId();
                    RestUtil.get(msgUrl);
                }
            }
        }
    }

    /**
     * 订单反审核
     *
     * @param order
     */
    @Override
    public void antiApprove(OmsOrder order) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        //如果有消费折扣，需要进行还原
        if (order.getProductDiscountAmount().compareTo(BigDecimal.ZERO) > 0
                || order.getPromotionDiscountAmount().compareTo(BigDecimal.ZERO) > 0
                || order.getMissionDiscountAmount().compareTo(BigDecimal.ZERO) > 0
                || order.getAdjustDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
            //获取使用的优惠卷记录
            OmsOrderDiscountRecord discountRecord = discountRecordService.getByOrderId(order.getId());
            if (discountRecord != null) {
                //折扣记录设置成回退状态
                discountRecord.setUseStatus(2);
                discountRecord.setUpdateTime(new Date());
                discountRecord.setUpdateBy(sysUser.getUsername());
                discountRecordService.updateById(discountRecord);
            }
        }
        //重置订单上的日期和状态因为日期字段设置null不更新所以单独写sql方法
        omsOrderMapper.antiApprove(order.getId());
    }

    //查询当前订单提交时间之前已经初审过的订单
    @Override
    public List<OmsOrder> getAuditOrderList(OmsOrder order) {
        LambdaQueryWrapper<OmsOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OmsOrder::getStoreId, order.getStoreId())
                .eq(OmsOrder::getStatus, 5)
                .eq(OmsOrder::getDeleteStatus, 0)
                .notIn(OmsOrder::getId, Arrays.asList(order.getId()))
                .le(OmsOrder::getCreateTime, order.getCreateTime());
        return list(wrapper);
    }

    //查询除当前订单外已初审订单
    @Override
    public List<OmsOrder> getOrderListByStoreId(String storeId, String orderId) {
        LambdaQueryWrapper<OmsOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OmsOrder::getStoreId, storeId)
                .eq(OmsOrder::getStatus, 5)
                .eq(OmsOrder::getDeleteStatus, 0)
                .notIn(OmsOrder::getId, Arrays.asList(orderId));
        return list(wrapper);
    }

    @Override
    public void updatePayOrderStatus() throws Exception {

        //查询更新时间在5分钟之内，并单订单状态为待支付的订单
        LambdaQueryWrapper<OmsOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OmsOrder::getStatus, 0)
                .ge(OmsOrder::getUpdateTime, DateUtil.offsetMinute(new Date(), -5));
        List<OmsOrder> orderList = list(wrapper);
        if (!orderList.isEmpty()) {
            for (OmsOrder order : orderList) {
                if (order.getVbeln() == null) {
                    continue;
                }
                String accessTokenNoCache = getAccessTokenNoCache();
                Map<String, String> req = new HashMap<>();
                req.put("mchid", "1700727696");
                req.put("out_trade_no", order.getVbeln());
                String pay = calcPaySig("/retail/B2b/getorder", JSON.toJSONString(req), "3fNN9fSnKLARv1uONEH1kYitTnmZdfnN");
                String url = "https://api.weixin.qq.com/retail/B2b/getorder?access_token=" + accessTokenNoCache + "&pay_sig=" + pay;
                HttpResponse execute = HttpUtil.createPost(url).body(JSON.toJSONString(req)).execute();
                String post = execute.body();
                com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(post);
                log.info("订单支付状态：" + jsonObject.toJSONString());
                if ("40001".equals(jsonObject.getString("errcode"))) {
                    //清空redis
                    redisUtil.del("access_token");
                    continue;
                }
                String payStatus = jsonObject.getString("pay_status");
                if ("ORDER_PAY_SUCC".equals(payStatus)) {
                    //更新订单状态为已支付
                    //根据订单
                    order.setStatus(1);
                    order.setPayStatus(4);
                    order.setUpdateTime(new Date());
                    updateById(order);
                }

            }
        }

    }

    /**
     * 获取即时订单
     */
    @Override
    public void updateOutStockStatusRedis() throws Exception {
        //从redis中可能支付的订单
        Object pay1 = redisUtil.get("pay");
        if (pay1 != null) {
            //将其转换为订单列表
            List<OmsOrder> orderList = JSON.parseArray(pay1.toString(), OmsOrder.class);
            //查询更新时间在5分钟之内，并单订单状态为待支付的订单
            if (!orderList.isEmpty()) {
                for (OmsOrder order : orderList) {
                    if (order.getVbeln() == null) {
                        continue;
                    }
                    String accessTokenNoCache = getAccessTokenNoCache();
                    Map<String, String> req = new HashMap<>();
                    req.put("mchid", "1700727696");
                    req.put("out_trade_no", order.getVbeln());
                    String pay = calcPaySig("/retail/B2b/getorder", JSON.toJSONString(req), "3fNN9fSnKLARv1uONEH1kYitTnmZdfnN");
                    String url = "https://api.weixin.qq.com/retail/B2b/getorder?access_token=" + accessTokenNoCache + "&pay_sig=" + pay;
                    HttpResponse execute = HttpUtil.createPost(url).body(JSON.toJSONString(req)).execute();
                    String post = execute.body();
                    com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(post);
                    log.info("订单支付状态：" + jsonObject.toJSONString());
                    if ("40001".equals(jsonObject.getString("errcode"))) {
                        //清空redis
                        redisUtil.del("access_token");
                        continue;
                    }
                    String payStatus = jsonObject.getString("pay_status");
                    if ("ORDER_PAY_SUCC".equals(payStatus)) {
                        //更新订单状态为已支付
                        //根据订单
                        order.setStatus(1);
                        order.setPayStatus(4);
                        order.setUpdateTime(new Date());
                        updateById(order);
                        //删除redis订单
                        redisUtil.del("pay:" + order.getVbeln());
                    }

                }
            }
        }


    }

    private static final String HMAC_SHA256 = "HmacSHA256";

    public static String calcPaySig(String uri, String postBody, String appkey) throws Exception {
        return calculateSignature(HMAC_SHA256, appkey, uri + "&" + postBody);
    }

    private static String calculateSignature(String algorithm, String key, String data) throws Exception {
        Mac mac = Mac.getInstance(algorithm);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm);
        mac.init(secretKeySpec);
        byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return bytesToHex(hash);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }

    public String getAccessTokenNoCache() {
        cn.hutool.json.JSONObject jsonParam = new cn.hutool.json.JSONObject();
        Object accessToken = redisUtil.get("access_token");

        if (accessToken != null) {
            return accessToken.toString();
        } else {
            String resultStr = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxcbee50c90eb18d3c&secret=203df958410937abbf0763c305f8e9b3";
            String s = HttpUtil.get(resultStr);
            JSONObject json = JSONUtil.parseObj(s);

            log.error("请求accesstoken报错：resultStr={}", resultStr);
            String accessToken1 = json.getStr("access_token");
            redisUtil.set("access_token", accessToken1, 7000);
            return accessToken1;
        }


    }
}
